package com.googlecode.cswish.struts.spring.generator;

import static com.googlecode.cswish.asm.Opcodes.ALOAD;
import static com.googlecode.cswish.asm.Opcodes.ARETURN;
import static com.googlecode.cswish.asm.Opcodes.DLOAD;
import static com.googlecode.cswish.asm.Opcodes.DRETURN;
import static com.googlecode.cswish.asm.Opcodes.FLOAD;
import static com.googlecode.cswish.asm.Opcodes.FRETURN;
import static com.googlecode.cswish.asm.Opcodes.ILOAD;
import static com.googlecode.cswish.asm.Opcodes.IRETURN;
import static com.googlecode.cswish.asm.Opcodes.LLOAD;
import static com.googlecode.cswish.asm.Opcodes.LRETURN;
import static com.googlecode.cswish.asm.Opcodes.RETURN;
import static com.googlecode.cswish.asm.Opcodes.*;

import com.googlecode.cswish.asm.MethodVisitor;

/**
 * A helper class to reduce the duplicate codes
 * 
 * @author Jerry.feng Date: 2008-9-23
 */
public class MethodVisitorHelper {

	protected final static void visitReturn(MethodVisitor mv, Class<?> clazz) {
		if (clazz != null) {
			if (clazz.isPrimitive()) {
				if (clazz == double.class) {
					mv.visitInsn(DRETURN);
				} else if (clazz == float.class) {
					mv.visitInsn(FRETURN);
				} else if (clazz == long.class) {
					mv.visitInsn(LRETURN);
				} else {
					mv.visitInsn(IRETURN);
				}
			} else {
				mv.visitInsn(ARETURN);
			}
		} else {
			mv.visitInsn(RETURN);
		}
	}
	
	protected final static void visitLoad(MethodVisitor mv, int var, Class<?> clazz) {
		if (clazz.isPrimitive()) {
			if (clazz == double.class) {
				mv.visitVarInsn(DLOAD, var);
			} else if (clazz == float.class) {
				mv.visitVarInsn(FLOAD, var);
			} else if (clazz == long.class) {
				mv.visitVarInsn(LLOAD, var);
			} else {
				mv.visitVarInsn(ILOAD, var);
			}
		} else {
			mv.visitVarInsn(ALOAD, var);
		}
	}
	
	// Integer obj;
	// ==>
	// int i = obj.intValue();
	// int i = obj;
	protected final static void convertToPrivimitive(MethodVisitor mv, Class<?> clazz) {
		if (clazz == int.class) {
			mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I");
		} if (clazz == boolean.class) {
			mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z");
		} else if (clazz == double.class) {
			mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D");
		} else if (clazz == long.class) {
			mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J");
		} else if (clazz == char.class) {
			mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C");
		} else if (clazz == byte.class) {
			mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B");
		} else if (clazz == float.class) {
			mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F");
		} else if (clazz == short.class) {
			mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S");
		}  
	}
	
	// int i;
	// ==>
	// Integer obj = Integer.valueOf(i)
	// Integer obj = 1;
	protected final static void convertToObject(MethodVisitor mv, Class<?> clazz) {
		if (clazz == int.class) {
			mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;");
		} if (clazz == boolean.class) {
			mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;");
		} else if (clazz == double.class) {
			mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;");
		} else if (clazz == long.class) {
			mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;");
		} else if (clazz == char.class) {
			mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;");
		} else if (clazz == byte.class) {
			mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;");
		} else if (clazz == float.class) {
			mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;");
		} else if (clazz == short.class) {
			mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;");
		}  
	}
	
	protected final static Class<?> getType(Class<?> primitiveClass) {
		if (primitiveClass == int.class) {
			return Integer.class;
		} if (primitiveClass == boolean.class) {
			return Boolean.class;
		} else if (primitiveClass == double.class) {
			return Double.class;
		} else if (primitiveClass == long.class) {
			return Long.class;
		} else if (primitiveClass == char.class) {
			return Character.class;
		} else if (primitiveClass == byte.class) {
			return Byte.class;
		} else if (primitiveClass == float.class) {
			return Float.class;
		} else if (primitiveClass == short.class) {
			return Short.class;
		} 
		return Void.class;
	}
	
	
}
